﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace zijian666.Core;

/// <summary>
/// 对象属性集合
/// </summary>
public class PropertiesCollection : IReadOnlyList<PropertyHandler>, IReadOnlyDictionary<string, PropertyHandler>
{
    /// <summary>
    /// 描述一个空集合
    /// </summary>
    public static PropertiesCollection Empty { get; } = new PropertiesCollection(new List<PropertyHandler>(0));

    /// <summary>
    /// 用于保存属性处理程序
    /// </summary>
    private readonly List<PropertyHandler> _properties;

    /// <summary>
    /// 构造函数
    /// </summary>
    public PropertiesCollection(List<PropertyHandler> properties) => _properties = properties ?? throw new ArgumentNullException(nameof(properties));

    /// <summary>
    /// 根据属性名查询属性的索引
    /// </summary>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    public (int index, PropertyHandler? hanlder) GetProperty(string propertyName)
    {
        if (string.IsNullOrWhiteSpace(propertyName))
        {
            return (-1, null);
        }

        propertyName = propertyName.Trim();
        for (var i = 0; i < _properties.Count; i++)
        {
            var p = _properties[i];
            if (p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
            {
                return (i, p);
            }
        }
        return (-1, null);
    }

    /// <summary>
    /// 判断是否存在指定的属性名
    /// </summary>
    public bool Contains(string propertyName) => GetProperty(propertyName).index >= 0;

    /// <summary>
    /// 根据属性名获取属性处理程序
    /// </summary>
    /// <param name="propertyName">属性名称</param>
    /// <returns></returns>
    public PropertyHandler? this[string propertyName] => GetProperty(propertyName).hanlder;
    /// <summary>
    /// 获取属性处理程序
    /// </summary>
    public PropertyHandler? this[int index]
    {
        get
        {
            if (index < 0 || index >= Count)
            {
                return null;
            }
            return _properties[index];
        }
    }

    /// <inheritdoc />
    public IEnumerable<string> Keys
    {
        get
        {
            foreach (var property in _properties)
            {
                yield return property.Name;
            }
        }
    }

    /// <inheritdoc />
    public IEnumerable<PropertyHandler> Values => _properties;

    /// <inheritdoc />
    IEnumerator<KeyValuePair<string, PropertyHandler>> IEnumerable<KeyValuePair<string, PropertyHandler>>.GetEnumerator()
    {
        foreach (var property in _properties)
        {
            yield return new KeyValuePair<string, PropertyHandler>(property.Name, property);
        }
    }

    /// <inheritdoc />
    public int Count => _properties.Count;

    /// <inheritdoc />
    IEnumerator IEnumerable.GetEnumerator() => _properties.GetEnumerator();

    /// <inheritdoc />
    PropertyHandler IReadOnlyDictionary<string, PropertyHandler>.this[string key] => this[key] ?? throw new KeyNotFoundException();

    /// <inheritdoc />
    PropertyHandler IReadOnlyList<PropertyHandler>.this[int index] => this[index] ?? throw new IndexOutOfRangeException();

    /// <inheritdoc />
    IEnumerator<PropertyHandler> IEnumerable<PropertyHandler>.GetEnumerator() => _properties.GetEnumerator();

    /// <inheritdoc />
    bool IReadOnlyDictionary<string, PropertyHandler>.ContainsKey(string key) => GetProperty(key).index >= 0;

#pragma warning disable CS8769 
    /// <inheritdoc />
    bool IReadOnlyDictionary<string, PropertyHandler>.TryGetValue(string key, out PropertyHandler? value)
    {
        (var index, value) = GetProperty(key);
        return index != -1;
    }
#pragma warning restore CS8769 
}
